AWS Well-Architected FrameworkのServerless Applications Lensを読んでみた
西澤です。Well-Architected Frameworkのうち、特別なアーキテクチャ専用にさらにその内容を掘り下げた資料が、Well-Architected Lensです。まず最初に、HPCとServerless用が公開され、先日IoT版も追加で作成されています。Serverless版の初版が発表されたのはもうかなり前なのですが、この中から今回は改めてServerless Applications Lensの内容について、簡単にまとめてみようと思います。原文は英語なので、雑に端折ってしまったところもあるとは思うのですが、間違っているような箇所があればご指摘いただけると嬉しいです。
ちなみに、HPC on AWSのLensについては、下記記事をご覧ください。
また、IoT Lensについては、下記記事でも触れられていますので、お読みいただけると嬉しいです。
定義
- Computer Layer
- ビジネスロジックを動作させるコンピューティング層として、以下のサービスを利用する
- AWS Lambda
- Amazon API Gateway
- AWS Step Functions
- Data Layer
- DB層としては、以下のサービスを利用する
- Amazon DynamoDB(Streams,Accelerator含む)
- Amaonz S3
- Amazon ES
- AWS AppSync
- Messaging and Streaming Layer
- コンポーネント間のメッセージングまたはストリーミングデータ処理として、以下のサービスを利用する
- Amazon SNS
- Amazon Kinesis(Data Analytics含む)
- Amazon Kinesis Firehose
- User Managemnent and Identity Layer
- ユーザまたはID管理として、以下のサービスを利用する
- Amazon Cognito
- System Monitoring and Deployment
- システム監視またはデプロイ管理として、以下のサービスを利用する
- Amazon CloudWatch
- AWS X-Ray
- AWS SAM
- Deployment Approaches
- 以下のデプロイ手法が考えられます。
- All at once
- 同時実行性が低い環境向け
- ロールバック時にダウンタイムが大きい
- 開発環境向け
- Blue/Green
- ほぼゼロダウンタイムでロールバックも容易
- 本番環境向け
- Canaries/Linear
- API Gatewayの機能でCanary Deploymentが可能
- 新機能の段階的リリース向け
- Lambda Version Control
- Lambdaのバージョン管理機能を利用する
- Edge Layer
- エッジ層として、以下のサービスを利用する
- CloudFront
一般的なデザイン原則
- Speedy, simple, singular
- 効率的でシンプルに
- For Scalability, Think concurrent requests
- スケーラビリティ、同時接続性を優先
- Share nothing
- 所謂シェアード・ナッシングである
- Assume no hardware affinity
- ハードウェアに依存しない
- Orchestrate multiple functions of your application with state machines
- Lambdaをステートマシンを使ってオーケストレーション
- Use events to trigger transactions
- イベント駆動な非同期処理
- Design for failures and duplicates
- イベントは失敗または複数回実行されることを想定する
シナリオ
Serverless構成が利用される5つのシナリオについて整理
- RESTful Microservices
- 特徴
- セキュア、運用しやすい、コピー可能、高可用性
- 継続的な改善の為のロギング
- 可能な限りマネージドサービスを利用
- アーキテクチャ
- 注意
- API Gatewayのログを活用し、可視化する
- 顧客のロケーションを理解する
- 顧客のリクエストによるデータベースへの影響を理解する
- セキュリティ観点での異常時の挙動を理解する
- パフォーマンス最適化の為の指標について理解する
- Alexa Skills
- 特徴
- インスタンスやサーバを管理しない
- コンテンツをスキルから分離
- 広範囲に向けて魅力的な音声体験を
- 弾力性、予期しないパターンの処理
- アーキテクチャ
- 注意
- スマートホームからの応答を検証
- Alexaの制限である8秒以内に応答
- VPC Lambdaはコールドスタートの問題がある点に注意
- DynamoDBのベストプラクティスに準拠
- Best Practices for DynamoDB - Amazon DynamoDB
- アカウントリンクのガイドラインに準拠
- 10 Tips for Successfully Adding Account Linking to Your Alexa Skill : Alexa Blogs
- Betaテスティングツールを利用
- ASK CLIを活用して開発やデプロイを自動化
- Mobile Backend
- 特徴
- クライアントからのアクセスに対しどのデータを返すのかを制御
- ビジネスロジックをモバイルアプリから分離
- マルチプラットフォームに対応する為、APIで機能を提供
- 可能な限りマネージドサービスを利用
- 利用していないものにコストをかけず最適化
- アーキテクチャ
- 注意
- Lambda実行環境のメモリやタイムアウトを最適化
- GitHub - alexcasalboni/aws-lambda-power-tuning: Step Functions state machine generator for AWS Lambda Power Tuning
- DynamoDBのベストプラクティスに準拠
- Best Practices for DynamoDB - Amazon DynamoDB
- AWS AppSync client SDKを使ってパフォーマンス最適化
- Amazon ESのベストプラクティスに準拠
- Managing Amazon Elasticsearch Service Domains - Amazon Elasticsearch Service
- Designing for Scale | Elasticsearch: The Definitive Guide [2.x] | Elastic
- Lambda実行回数を最低限とし、API層でキャッシュする
- AWS AppSyncをAWS IAMやCognito User Poolsを利用してアクセス制御
- AWS AmplifyとAmplify CLIを活用
- Steream Processing
- 特徴
- 可能な限りマネージドサービスを利用
- Amazon Kinesis Producer Libraryで取り込みを制御
- アーキテクチャ
- 注意
- Kinesis Data Streamのベストプラクティスに準拠
- Resharding, Scaling, and Parallel Processing - Amazon Kinesis Data Streams
- Streaming Data Solutionsホワイトペーパーに準拠
- https://d0.awsstatic.com/whitepapers/whitepaper-streaming-data-solutions-on-aws-with-amazon-kinesis.pdf
- KPLを利用しない場合は、部分的な失敗を考慮する
- レコードの重複は起こることを想定する
- Handling Duplicate Records - Amazon Kinesis Data Streams
- S3等に格納が必要なデータでは、Kinesis Firehoseを検討する
- ストリームデータをクエリする場合は、Kinesis Analyticsを検討する
- Lambdaのストリームイベント呼び出しのベストプラクティスに準拠する
- Best Practices for Working with AWS Lambda Functions - AWS Lambda
- Web Application
- 特徴
- スケーラブル、高可用性
- 適切なレスポンス、一貫したユーザ体験
- 可能な限りマネージドサービスを利用
- 利用していないものにコストをかけず最適化
- セットアップや運用が簡単なフレームワーク
- アーキテクチャ
- 注意
- サーバレスWEBアプリケーションフロントエンドのベストプラクティスに準拠、S3のWEBホスティング利用、CloudFront活用
- SPAでは、S3バージョニング活用、CloudFrontキャッシュやTTL設定に注意
- 認証についてはセキュリティの柱を参考に
- バックエンドは、RESTful Microservicesのシナリオを参考に
- ユーザ別の顧客体験を用意する場合には、API Gatewyの使用量プランを活用
- API キーを使用する使用量プランの作成と使用 - Amazon API Gateway
- Mobile Backendシナリオも参考に
Well-Architected Frameworkの5本の柱
- Operational Excellence
- ベストプラクティス
- Prepare
- 特になし
- Operate
- サーバレスアプリケーションの異常をどのように監視し対処するか?
- AWS X-Rayによる追跡
- Service Mapsの活用
- アラーム設定
- Lambda: Throttling, Errors, ConcurrentExecutions,UnreservedConcurrentExecutions
- Step Functions: ActivitiesTimedOut, ActivitiesFailed,ActivitiesHeartbeatTimedOut
- API Gateway: 5XXError, 4XXError
- 以下の観点でダッシュボード化
- Business Metrics
- Customer Experience metrics
- System Metrics
- Operational Metrics
- 変更の影響を最小化しつつ、サーバレスアプリケーションをどのように進化させていくのか?
- API Gateway endpoints, Lambda functions, Step Functions state machinesなどのリソースを各ステージでバージョン管理
- Canary or Linear deployment、CodeDeploy Hooksを活用
- AWS SAM、SAM CLIを活用
- Lambda環境変数で各環境の構成を分離
- より高度なアクセス制御が必要であれば、SSM Parameter Storeも活用
- SAM CLIはローカルテストにおいては強力だが、パフォーマンス試験は本番相当の環境で
- API Gatewayステージ変数とLambdaエイリアス/バージョンは、ステージ分離の為に利用すると運用が複雑になるので避ける
- CloudWatchメトリクスと共にX-Rayを活用
- Evolve
- 特になし
- Key AWS Services
- SSM Parameter Store
- SAM
- CloudWatch
- AWS CodePipeline
- AWS X-Ray
- Lambda
- API Gateway
- Security
- ベストプラクティス
- Identity and access management
- サーバレスAPIに対する認証・認可をどう実現するか?
- API Gatewayでは、以下から要件に合わせて利用可能
- AWS_IAM authorization
- Amazon Cognito user pools
- API Gateway Lambda authorizer
- Resource Policies
- Lambda関数からのアクセス範囲を管理しているか?
- 最低限のアクセス許可
- 同一IAMロールの複数Lambdaでの使い回しを避ける
- Detective controls
- サーバレスアプリケーションログをどのように分析しているか?
- CloudWatch Logsのフィルター設定による通知
- CloudTrailログの監視
- API Gatewayアクセスログの有効化
- Lambdaからのログはパフォーマンス劣化やコストとなるケースもあるので注意する
- サーバレスアプリケーションの脆弱性をどのように監視するか?
- OWASP Dependency CheckをCI/CDパイプラインに組み込む
- AWS SDKを含むすべてのソフトウェアバージョン管理を行う
- Infrastructure Protection
- Lambdaがアクセス可能なVPCの境界をどのように管理するか?
- AWS Well-Architected FrameworkのSecurity Groupベストプラクティスに準拠する
- NACLも活用
- コードの外でも境界を設ける
- Data Protection
- サーバレスアプリケーション上でセンシティブな情報をどのように取り扱うか?
- 通信上はTLSを使っていても、リクエストパスやクエリストリングに情報が埋め込まれていたり、復号化された後の情報がCloudWatch Logsに出力されるようなケースに注意
- 外部からの攻撃が行われるケースも
- センシティブデータはすべてのレイヤにおいて常に保護されている必要がある
- API Gateway利用では、ヘッダー等を含むすべてのデータがクライアントサイドで暗号化されている必要がある
- API Gatewayログ、CloudWatch Logsに出力されるLambdaログ等にも注意
- インプットの検証をどうするか?
- API Gatewayにてリクエストの検証を有効化する
- API Gateway でリクエストの検証を有効化する - Amazon API Gateway
- アプリ層でも別に入力検証ロジックを実装する
- Key AWS Service
- Amazon Cognito
- IAM
- Lambda
- CloudWatch Logs
- AWS CloudTrail
- AWS CodePipeline
- Amazon S3
- Amazon ES
- DynamoDB
- Amazon VPC
- Reliability
- ベストプラクティス
- Foundations
- ピーク負荷時の上限について考慮しているか?
- AWSサービスの制限に注意
- Trusted Advisorから上限の80%で通知する仕組みも可
- 関連するすべてのAWSアカウントとリージョンで
- 処理を非同期に
- サーバレスアプリケーションへのアクセスレートをどのように制限するか?
- Throttlingを有効に
- APIキーを使用する使用量プランも活用
- ログを残し、追跡かのうにしておく
- APIキーはセキュアなメカニズムではない
- Lambdaの同時実行数制御も利用
- 同時実行数の管理 - AWS Lambda
- 同時実行数制御が有効なシナリオ
- スケーラビリティに制限があるセンシティブなバックエンドシステム
- DBコネクションプール制限
- クリティカルパスサービス、優先度高のLambda
- 異常が発生した場合にLambda関数を無効にする(concurrency=0)
- DDoS対策
- 非同期呼び出しやイベントをどうするか?
- 同期呼び出しを避け、イベント駆動で非同期な処理を行う
- フロントエンド側でロジックを分離し、処理を中止できるようにしておく
- どうしても同期処理が必要な場合には、API Gatewayのタイムアウトに注意
- サーバレスアプリケーションのテストをどうするか?
- CloudWatch Logsに最大メモリを記録
- VPC Lambdaを利用する場合、利用可能なIPアドレス数に注意
- モジュール化されたコードを別ファンクションで用意し、ユニットテストを可能に
- 外部接続用のコードを再利用可能な別ファンクションで用意し、接続数制限を回避
- DynamoDBのキャパシティやAuto Scalingを随時調整
- その他のサービス制限についても考慮する
- サーバレスアプリケーションの回復力は?
- Change Management
- 正常な状態を定義し、異常な状態を検知可能、かつ、追跡可能にする
- SAM Safe Deployments も活用
- Gradual
- Failure Management
- Lambdaでは、ロギングおよびリトライロジックを
- AWS SDKに実装されたリトライメカニズムも活用
- X-RayやAPMで監視
- 非同期処理失敗時のDLQ利用
- カスタムtry/catch、バックオフ、リトライを避ける為、Step Functionsを活用
- PutRecoreds(Kinesis)やBatchWriteItem(DynamoDB)等の部分的に失敗する可能性があるものは、他からもチェックする
- ロールバックが必要な同期処理はSaga patternで実装
- Applying the Saga pattern with AWS Lambda and Step Functions | theburningmonk.com
- Key AWS Services
- AWS Marketplace
- Trusted Advisor
- CloudWatch Logs
- CloudWatch
- API Gateway
- Lambda
- X-ray
- Step Functions
- Amazon SQS
- and Amazon SNS
- Performance Efficiency
- Selection
- サーバレスアーキテクチャの最適なキャパシティをどのように選択するか?
- Lambdaのメモリ使用量、Kinesisのシャード数、DynamoDBキャパシティ等の決定をどうするか?
- デフォルトでも多すぎても少なすぎてもダメ
- 必ずテストを行った上で決める
- 依存関係のある上位サービスのタイムアウトから確認
- Optimize
- サーバレスアプリケーションのパフォーマンスをどのように最適化したか?
- API Gatewayキャッシング、DAX、DynamoDBのグローバル/セカンダリインデックス等を検討する
- API Gatewayのコンテンツエンコードはデフォルト無効なので、検討の余地あり
- Lambdaのメモリ、タイムアウト設定をテスト
- Deployment
- VPC Lambdaはなるべく避ける
- VPC Lambdaの場合、NAT Gatewayが必須
- API Gatewayは、Edge-optimizedとRegional Endpointの2種類があるので理解して使い分ける
- どの要素をVPCに配置するかをどう決定するか?
- RDS/Elasticach等のVPC内のリソースにアクセスが必要?
- インターネット上のパブリックサービスへのアクセスが必要?
- Code Optimization
- Lambdaのコードをどのようにパフォーマンス最適化するのか?
- Lambdaのベストプラクティスに準拠する
- コンテナー再利用、パッケージサイズの最小化、依存関係の複雑性を最小化、等
- AWS Lambda 関数を使用する際のベストプラクティス - AWS Lambda
- VPC Lambdaを利用する場合、VPCのパブリックホスト名設定を無効にしておいた方が早い
- どのようにデータベース接続を初期化するか?
- 再利用可能なように、Lambda関数ハンドラコードの外側でのデータベース接続も検討
- どのように非同期トランザクションを実装するのか?
- Serverless Data Processing
- Kinesis Data Firehose での入力レコード形式の変換 - Amazon Kinesis Data Firehose
- Serverless event submission with status updates
- その他
- Review、Monitoring、TradeoffsについてはAWS Well-Architected Frwameworkのホワイトペーパーを参照
- Key AWS Services
- DynamoDB Accelerator
- API Gateway
- Step Functions
- NAT gateway
- Amazon VPC
- Lambda
- Cost Optimization
- ベストプラクティス
- Cost-Effective Resources
- Lambdaのメモリ割り当ての決定戦略は?
- 時間がかかるので、少なければ良いというわけではない
- Matching Supply and Demand
- 需要に応じてスケールされるようデザインされているので問題なし
- Expenditure Awareness
- サーバレスアーキテクチャーが成長するに連れて、かかる費用も大きくなる為、事前の計画が必要
- LambdaもAPI Gatewayもタグベースの課金情報管理が可能
- Optimizing Overtime
- Lambdaファンクションにおけるロギング戦略は?
- CloudWatch Logsへの課金に注意しつつ、必要なログのみ出力する
- 15.7. logging — Logging facility for Python — Python 2.7.16 documentation
- Log保存期間を設定してストレージを節約
- より安価なS3やESにログをエキスポート
- 不要なLambda関数を実行していないか?
- Lambda関数は、データを変形する為に利用し、データを運ぶ為に使ってはならない
- API Gatewayから実行しているLambda関数がデータを渡しているだけなら、AWS Service Proxy機能でAPI Gatewayから直接サービスにデータを渡すように構成変更する
- 場合によっては、クライアントSDKを使って、AWSサービスに直接処理する(API Gatewayが無くせる)構成も検討
- Lambdanの総実行時間を減らせないか?
- 待ち処理などのロジックをStep Functionsにオフロード
- S3からデータを取り出すのであれば、AthenaやS3 Selectも検討する
まとめ
何気なく読み始めたところ、思った以上に時間がかかってしまったのです。サーバレスアーキテクチャはチャレンジングなアーキテクチャである為、特に運用や監視のあたりは標準的な手法が確立されていない印象がありましたが、AWS側からも具体的な情報やパターンが示されていた為、非常に読み応えのあり、且つ、実際にサーバレスアーキテクチャを検討されている方には実効性のある資料になっていると思いました。個人的には、例えば非同期にすることが原則でありながら、同期処理を実装しなければいけないときにどのような方法や考慮が必要なのか、等というような理想論に留まらず、実践的に書かれているところがすごく良いと思いました。ポイントポイントでの参考文献の紹介も充実していました。興味が湧いた方がいらっしゃれば、ぜひ読んでみていただければと思います。
どこかの誰かのお役に立てば嬉しいです。